// 测试weak_ptr
// 作为一个旁观者来监视 shared_ptr 中管理的资源是否存在。
// weak_ptr 还可以用来返回 this 指针和解决循环引用的问题。
// std::weak_ptr 的设计和语义决定了它不能像
// std::shared_ptr 那样直接通过初始化列表来初始化
// 所以可以选择后面在给他链接上shared_ptr

// 基本用法
#include <iostream>
#include <memory>

// 通过weak_ptr观察引用计数
// 不会更改count
void test_weak_ptr1()
{
    std::shared_ptr<int> p1 = std::make_shared<int>(10);
    std::weak_ptr<int> p2 = p1;
    std::cout << "p1 use_count: " << p1.use_count() << std::endl;
    std::cout << "p2 use_count: " << p2.use_count() << std::endl;
}

// 观察资源是否过期
void test_weak_ptr2()
{
    std::shared_ptr<int> p1 = std::make_shared<int>(10);
    std::weak_ptr<int> p2 = p1;
    if (p2.expired())
    {
        std::cout << "p2 is expired" << std::endl;
    }
    else
    {
        std::cout << "p2 is not expired" << std::endl;
    }
    // 增加一个过期的例子
    std::shared_ptr<int> p3 = std::make_shared<int>(10);
    std::weak_ptr<int> p4 = p3;
    p3.reset();
    if (p4.expired())
    {
        std::cout << "p4 is expired" << std::endl;
    }
    else
    {
        std::cout << "p4 is not expired" << std::endl;
    }
}
// 通过weak_ptr获取shared_ptr
void test_weak_ptr3()
{
    std::shared_ptr<int> p1 = std::make_shared<int>(10);
    std::weak_ptr<int> p2 = p1;
    auto p3 = p2.lock();
    std::cout << "p3 use_count: " << p3.use_count() << std::endl;
}
// 循环引用示例
//  循环引用
//  循环引用的例子
struct Node
{
    std::shared_ptr<Node> next;
    int data;
    ~Node()
    {
        std::cout << "Destroying node with data: " << data << std::endl;
    }
};

void circular_reference()
{
    std::shared_ptr<Node> node1(new Node{nullptr, 1});
    std::shared_ptr<Node> node2(new Node{nullptr, 2});

    // 创建循环引用
    node1->next = node2;
    node2->next = node1;

    // 此时node1和node2的引用计数都是2
    std::cout << "node1 reference count: " << node1.use_count() << std::endl;
    std::cout << "node2 reference count: " << node2.use_count() << std::endl;

    // 函数结束时，node1和node2的引用计数减1，但仍然为1
    // 由于相互引用，引用计数永远不会为0
    // 导致内存泄漏，析构函数永远不会被调用
}
struct NodeWeak
{ // 改名以区分原来的 Node
    std::weak_ptr<NodeWeak> next;
    // 增加一个构造函数传入data
    NodeWeak(int data) : data(data) {}
    int data;
    ~NodeWeak()
    {
        std::cout << "Destroying node with data: " << data << std::endl;
    }
};

void circular_reference_with_weak_ptr()
{ // 新的函数名
    std::shared_ptr<NodeWeak> node1(new NodeWeak{1});
    std::shared_ptr<NodeWeak> node2(new NodeWeak{2});

    // 创建循环引用
    node1->next = node2;
    node2->next = node1;

    // 要访问 next 指向的节点，需要先通过 lock() 获取 shared_ptr
    if (auto next1 = node1->next.lock())
    {
        std::cout << "Node1's next data: " << next1->data << std::endl;
    }

    if (auto next2 = node2->next.lock())
    {
        std::cout << "Node2's next data: " << next2->data << std::endl;
    }

    // 演示资源失效的情况
    node2.reset(); // 释放 node2
    if (auto next1 = node1->next.lock())
    {
        std::cout << "Node1's next is still valid" << std::endl;
    }
    else
    {
        std::cout << "Node1's next has expired" << std::endl;
    }

    std::cout << "node1 reference count: " << node1.use_count() << std::endl;
}
int main()
{
    test_weak_ptr1();
    test_weak_ptr2();
    test_weak_ptr3();
    circular_reference();
    circular_reference_with_weak_ptr();
    return 0;
}
